#include "TimeStampFilter.h"
#include "common.h"

#include <InitGuid.h>
#include <iostream>

#pragma warning(disable:4710)  // 'function' not inlined (optimization)

// {4B047090-1AB4-4537-8DF4-80DA04FD39B5}
DEFINE_GUID(CLSID_TimeStampFilter, 
			0x4b047090, 0x1ab4, 0x4537, 0x8d, 0xf4, 0x80, 0xda, 0x4, 0xfd, 0x39, 0xb5);

//
// Setup data for filter registration
//
const AMOVIESETUP_MEDIATYPE sudOpPinTypes =
{ &MEDIATYPE_NULL     // clsMajorType
, &MEDIASUBTYPE_NULL }; // clsMinorType

const AMOVIESETUP_PIN psudPins[] =
{
	{L"Input"          // strName
	, FALSE              // bRendered
	, TRUE               // bOutput
	, FALSE              // bZero
	, FALSE              // bMany
	, &CLSID_NULL        // clsConnectsToFilter
	, L"Output"           // strConnectsToPin
	, 1                  // nTypes
	, &sudOpPinTypes} , // lpTypes

	{L"Output"          // strName
		, FALSE              // bRendered
		, TRUE               // bOutput
		, FALSE              // bZero
		, FALSE              // bMany
		, &CLSID_NULL        // clsConnectsToFilter
		, L"Input"           // strConnectsToPin
		, 1                  // nTypes
		, &sudOpPinTypes}  // lpTypes
};

const AMOVIESETUP_FILTER subFilter =
{ &CLSID_TimeStampFilter     // clsID
, L"Time stamp filter"  // strName
, MERIT_DO_NOT_USE                  // dwMerit
, 2                               // nPins
, psudPins };                    // lpPin


//
//  Object creation template
//
CFactoryTemplate g_Templates[1] = {
	{ L"Time stamp filter"
	, &CLSID_TimeStampFilter
	, TimeStampFilter::CreateInstance
	, NULL
	, &subFilter }
};

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);




TimeStampFilter::TimeStampFilter(HRESULT *hr):
CTransInPlaceFilter(L"Time Stamp Filter", NULL, CLSID_TimeStampFilter, hr),
m_IsStart(true)
{

}


void TimeStampFilter::start()
{
	m_IsStart = true;
}

void TimeStampFilter::stop()
{
	m_IsStart = false;
}

// HRESULT TimeStampFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
// {
// 	if (pMediaType == NULL)
// 	{
// 		return E_INVALIDARG;
// 	}
// 	if (iPosition == 0)
// 	{
// 		pMediaType->majortype = MEDIATYPE_Video;
// 		pMediaType->subtype = MEDIASUBTYPE_RGB32;
// 	}
// 	else if (iPosition == 1)
// 	{
// 		pMediaType->majortype = MEDIATYPE_Video;
// 		pMediaType->subtype = MEDIASUBTYPE_RGB24;
// 	}
// 	else if (iPosition == 2)
// 	{
// 		pMediaType->majortype = MEDIATYPE_Video;
// 		pMediaType->subtype = MEDIASUBTYPE_RGB565;
// 	}
// 	else if (iPosition == 3)
// 	{
// 		pMediaType->majortype = MEDIATYPE_Video;
// 		pMediaType->subtype = MEDIASUBTYPE_RGB555;
// 
// 	}else
// 	{
// 		return E_INVALIDARG;
// 	}
// 	return NOERROR;
// }

// HRESULT TimeStampFilter::DecideBufferSize(IMemAllocator *allocator, ALLOCATOR_PROPERTIES *ppropInputRequest)
// {
// 	HRESULT hr;
// 	int sampleSize = m_pInput->m_mt.GetSampleSize();
// 
// 	ppropInputRequest->cBuffers = 1;
// 	ppropInputRequest->cbAlign = 1;
// 	ppropInputRequest->cbBuffer = sampleSize;
// 
// 	std::cout<<"Time stamp sample size:"<<sampleSize<<std::endl;
// 
// 	ALLOCATOR_PROPERTIES actual;
// 	hr = allocator->SetProperties(ppropInputRequest, &actual);
// 	if (FAILED(hr))
// 	{
// 		return hr;
// 	}
// 
// 	retirm NOERROR;
// }

HRESULT TimeStampFilter::CheckInputType(const CMediaType* mtIn)
{
	if (IsStopped() && mtIn->majortype == MEDIATYPE_Video)
	{
		if (mtIn->subtype == MEDIASUBTYPE_RGB32||
			mtIn->subtype == MEDIASUBTYPE_RGB24 ||
			mtIn->subtype == MEDIASUBTYPE_RGB555 ||
			mtIn->subtype == MEDIASUBTYPE_RGB565)
		{
			return S_OK;
		}
	}
	return E_FAIL;
}

// HRESULT TimeStampFilter::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
// {
// 	if (mtIn->subtype == mtOut->subtype)
// 	{
// 		return S_OK;
// 	}
// 	return E_FAIL;
// }

HRESULT TimeStampFilter::Transform(IMediaSample *pSample)
{
	HRESULT hr;
	PBYTE dataPointer;
	hr = pSample->GetPointer(&dataPointer);
	if (FAILED(hr))
	{
		ErrorPrint("Get pointer from sample error",hr);
		return false;
	}

	CMediaType mediaType;
	hr = m_pInput->ConnectionMediaType(&mediaType);
	if (FAILED(hr))
	{
		ErrorPrint("Get connection media type error",hr);
		return false;
	}

	VIDEOINFOHEADER* header = (VIDEOINFOHEADER*)mediaType.pbFormat;
	HDC hdc = CreateCompatibleDC(NULL);
	if (hdc == NULL)
	{
		ErrorPrint("Create hdc error");
		return false;
	}

	BITMAPINFO  bmi;
	memset(&bmi,0,sizeof(BITMAPINFO));
	bmi.bmiHeader = header->bmiHeader;
	HBITMAP hBitmap = CreateDIBitmap(hdc, &(header->bmiHeader), CBM_INIT, dataPointer, &bmi, DIB_RGB_COLORS);
	if (hBitmap == NULL)
	{
		DeleteDC(hdc);
		ErrorPrint("Create bitmap error");
		return E_FAIL;
	}
	HGDIOBJ oldGdiObject = SelectObject(hdc, hBitmap);
	TextOut(hdc, 0, 0,L"Hello",5);
	SelectObject(hdc, oldGdiObject);

	int lines = GetDIBits(hdc, hBitmap, 0, bmi.bmiHeader.biHeight, dataPointer, &bmi, DIB_RGB_COLORS);
	DeleteObject(hBitmap);
	DeleteDC(hdc);
	if (lines == 0)
	{
		ErrorPrint("Get di bits error");
		return E_FAIL;
	}
	return S_OK;
}